package org.jeecg.modules.wangyue.controller.timer;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.wangyue.constant.*;
import org.jeecg.modules.wangyue.entity.*;
import org.jeecg.modules.wangyue.model.req.ReqCommonModel;
import org.jeecg.modules.wangyue.service.*;
import org.jeecg.modules.wangyue.utils.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* @Description: 定时器
* @Author: jeecg-boot
* @Date:   2023-07-24
* @Version: V1.0
*/
@Slf4j
@Api(tags="定时器")
@RestController
public class TimerController {

    @Autowired
    private ICoordinateJsService coordinateJsService;
    @Autowired
    private IUserBasicService userBasicService;
    @Autowired
    private IUserRoleInfoService userRoleInfoService;
    @Autowired
    private IIndentJsService indentJsService;
    @Autowired
    private IConfigurationService configurationService;
    @Autowired
    private IMyInfoService myInfoService;


    /**
     * 定时检测在线工作的技师是否还在活跃，如果不在则改为下线状态
     *
     * 时间：每分钟
     */
    @Async
    @Scheduled(cron = "0 0/1 * * * ?")
    public void checkOnlineJsForInactivationTimer(){
        String time = DateUtil.getTimeStr("yyyy-MM-dd HH:mm:ss");
        System.out.println("(" + time + ")定时器(检测在线技师是否失活)-触发");
        List<String> idList = coordinateJsService.getOnlineJsForInactivation();
        //如果有在线技师失活的，则处理状态为下线
        if(oConvertUtils.isNotEmpty(idList) && idList.size() > 0){
            List<UserRoleInfo> userRoleInfoList = new ArrayList<>();
            for(String id : idList){
                UserRoleInfo userRoleInfo = new UserRoleInfo();
                userRoleInfo.setId(id);
                userRoleInfo.setServiceStatus(ServiceStatusConstant.atRest);
                userRoleInfoList.add(userRoleInfo);
            }
            if(userRoleInfoService.updateBatchById(userRoleInfoList)){
                System.out.println("(" + time + ")定时器(检测在线技师是否失活)-成功(" + userRoleInfoList.size() + ")");
            }else {
                System.out.println("(" + time + ")定时器(检测在线技师是否失活)-失败(" + userRoleInfoList.size() + ")");
            }
        }else {
            System.out.println("(" + time + ")定时器(检测在线技师是否失活)-无数据,不作处理");
        }
    }


    /**
     * 定时处理待支付状态的订单，超时则改为关闭支付状态
     *
     * 时间：每分钟
     */
    @Async
    @Scheduled(cron = "0 0/1 * * * ?")
    public void indentStateTimer(){
        String time = DateUtil.getTimeStr("yyyy-MM-dd HH:mm:ss");
        System.out.println("(" + time + ")定时器(检测待支付订单是否超时)-触发");
        QueryWrapper<Configuration> configurationQueryWrapper = new QueryWrapper<>();
        configurationQueryWrapper.eq("id", ConfigParamConstant.noPayCancelTime); //订单N分钟未支付自动取消
        configurationQueryWrapper.eq("del_flag", DelFlagConstant.normal);
        Configuration configuration = configurationService.getOne(configurationQueryWrapper);

        QueryWrapper<IndentJs> indentJsQueryWrapper = new QueryWrapper<>();
        long timeDifference = CommonConstant.indentStateCheckTimeDifference;
        if(oConvertUtils.isNotEmpty(configuration) && oConvertUtils.isNotEmpty(configuration.getParamValue())){
            timeDifference = -1000L * 60 * Long.valueOf(configuration.getParamValue());
        }
        String sql = "create_time < '" + DateUtil.getTimeStrToMillis("yyyy-MM-dd HH:mm:ss", timeDifference) + "'";
        indentJsQueryWrapper.apply(sql);
        indentJsQueryWrapper.eq("order_status", OrderStatusConstant.toBePaid);  //待支付
        indentJsQueryWrapper.eq("del_flag", DelFlagConstant.normal);
        List<IndentJs> indentJsList = indentJsService.list(indentJsQueryWrapper);
        if(oConvertUtils.isNotEmpty(indentJsList) && indentJsList.size() > 0){
            List<IndentJs> indentJsList2 = new ArrayList<>();
            for(IndentJs indentJs : indentJsList){
                IndentJs indentJs2 = new IndentJs();
                indentJs2.setId(indentJs.getId());
                indentJs2.setOrderStatus(OrderStatusConstant.closePaid); //关闭支付
                indentJsList2.add(indentJs2);
            }
            if(indentJsService.updateBatchById(indentJsList2)){
                System.out.println("(" + time + ")定时器(检测待支付订单是否超时)-成功(" + indentJsList2.size() + ")");
            }else {
                System.out.println("(" + time + ")定时器(检测待支付订单是否超时)-失败(" + indentJsList2.size() + ")");
            }
        }else {
            System.out.println("(" + time + ")定时器(检测待支付订单是否超时)-无数据,不作处理");
        }
    }



    /**
     * 定时查看待服务订单，如果有订单在N分钟以后服务开始，则发送通知
     *
     * 时间：每分钟
     */
    @Async
    @Scheduled(cron = "0 0/1 * * * ?")
    public void orderServiceNoticeTimer(){
        String time = DateUtil.getTimeStr("yyyy-MM-dd HH:mm:ss");
        System.out.println("(" + time + ")定时器(查看是否有待服务订单,需要提前通知技师准备服务)-触发");
        //查询参数配置
        QueryWrapper<Configuration> configurationQueryWrapper = new QueryWrapper<>();
        configurationQueryWrapper.eq("id", ConfigParamConstant.noticeJsTime);
        configurationQueryWrapper.eq("del_flag", DelFlagConstant.normal);
        Configuration configuration = configurationService.getOne(configurationQueryWrapper);
        String noticeJsTime = "30"; //默认给30分钟(如果数据库配置，则用数据库的),服务开始前N分钟通知技师(分钟)
        if(oConvertUtils.isNotEmpty(configuration) && oConvertUtils.isNotEmpty(configuration.getParamValue())){
            noticeJsTime = configuration.getParamValue();
        }
        Date leftDate = new Date(System.currentTimeMillis() + 1000L * 60 * Long.valueOf(noticeJsTime)); //当前时间往后推N分钟
        Date rightDate = new Date(System.currentTimeMillis() + 1000L * 60 * (Long.valueOf(noticeJsTime) + 1)); //当前时间往后推N+1分钟
        String leftTime = DateUtil.getTimeStrByDate("yyyy-MM-dd HH:mm:ss", leftDate);
        String rightTime = DateUtil.getTimeStrByDate("yyyy-MM-dd HH:mm:ss", rightDate);
//        System.out.println("检测(" + leftTime + ")-(" + rightTime + ")");

        //查看需要提前通知技师服务N分钟后开始的
        QueryWrapper<IndentJs> indentJsQueryWrapper = new QueryWrapper<>();
        indentJsQueryWrapper.eq("order_status", OrderStatusConstant.toBeServed); //1-待服务
        indentJsQueryWrapper.eq("del_flag", DelFlagConstant.normal);
        String timeSql = "service_begin_time >= '" + leftTime + "' and service_begin_time < '" + rightTime + "'";
        indentJsQueryWrapper.apply(timeSql);
        List<IndentJs> indentJsList = indentJsService.list(indentJsQueryWrapper);
        if(oConvertUtils.isNotEmpty(indentJsList) && indentJsList.size() > 0){
            List<MyInfo> myInfoList = new ArrayList<>();
            for(IndentJs indentJs : indentJsList){
                MyInfo myInfo = new MyInfo();
                myInfo.setTitle("您有一笔订单在" + configuration.getParamValue() + "分钟之后服务开始，请提前准备");
                myInfo.setContent("订单编号：" + indentJs.getOrderNo() + "，服务开始时间：" +  DateUtil.getTimeStrByDate("yyyy-MM-dd HH:mm:ss", indentJs.getServiceBeginTime()));
                myInfo.setUserId(indentJs.getTakingUserId());
                myInfo.setUserType(indentJs.getTakingUserType());
                myInfo.setInfoType(MyInfoConstant.infoType_order); //订单消息
                myInfoList.add(myInfo);
            }
            if(myInfoService.saveBatch(myInfoList)){
                System.out.println("(" + time + ")定时器(查看是否有待服务订单,需要提前通知技师准备服务)-成功(" + myInfoList.size() + ")");
            }else {
                System.out.println("(" + time + ")定时器(查看是否有待服务订单,需要提前通知技师准备服务)-失败(" + myInfoList.size() + ")");
            }
        }else {
            System.out.println("(" + time + ")定时器(查看是否有待服务订单,需要提前通知技师准备服务)-无数据,不作处理");
        }

    }




    /**
     * 检测vip会员用户的vip是否过期
     *
     * 时间：每天凌晨0点1分(00:01:00)
     */
    @Async
    @Scheduled(cron = "0 1 0 * * ?")
    public void vipExpirationTimer(){
        String time = DateUtil.getTimeStr("yyyy-MM-dd HH:mm:ss");
        System.out.println("(" + time + ")定时器(检测vip会员用户的vip是否过期)-触发");
        //查出所有vip会员用户
        QueryWrapper<UserBasic> userBasicQueryWrapper = new QueryWrapper<>();
        userBasicQueryWrapper.eq("is_vip", IsVipConstant.yes);
        userBasicQueryWrapper.eq("del_flag", DelFlagConstant.normal);
        List<UserBasic> userBasicList = userBasicService.list(userBasicQueryWrapper);

        if(oConvertUtils.isNotEmpty(userBasicList) && userBasicList.size() > 0){
            //如果当前时间大于会员到期时间，则取消vip会员
            Date nowDate = DateUtil.getTime("yyyy-MM-dd HH:mm:ss"); //当前时间
            List<UserBasic> userBasics = new ArrayList<>();
            for(UserBasic userBasic : userBasicList){
                Date vipDate = userBasic.getVipDate(); //vip到期时间
                if(oConvertUtils.isEmpty(vipDate) || nowDate.after(vipDate)){ //vip会员到期时间“为空”或者“小于当前时间”，则取消vip会员
                    UserBasic uBasic = new UserBasic();
                    uBasic.setId(userBasic.getId());
                    uBasic.setIsVip(IsVipConstant.no);
                    userBasics.add(uBasic);
                }
            }
            if(userBasics.size() > 0){
                if(userBasicService.updateBatchById(userBasics)){
                    System.out.println("(" + time + ")定时器(检测vip会员用户的vip是否过期)-成功(" + userBasics.size() + ")");
                }else {
                    System.out.println("(" + time + ")定时器(检测vip会员用户的vip是否过期)-失败(" + userBasics.size() + ")");
                }
            }else {
                System.out.println("(" + time + ")定时器(检测vip会员用户的vip是否过期)-无过期会员数据,不作处理");
            }
        }else {
            System.out.println("(" + time + ")定时器(检测vip会员用户的vip是否过期)-无会员数据,不作处理");
        }
    }



}
